using System;
using Headspring.Training.Core.Model;
using Headspring.Training.Core.Services;
using Headspring.Training.Infrastructure.Impl;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;

namespace Headspring.Training.UnitTests.Services
{
	[TestFixture]
	public class StateCommandVisitorTester
	{
		public class MockWorkOrderRepository : IWorkOrderRepository
		{
			public WorkOrder WorkOrderSaved;

			public void Save(WorkOrder workOrder)
			{
				WorkOrderSaved = workOrder;
			}

			public WorkOrder GetWorkOrder(string number)
			{
				throw new NotImplementedException();
			}

			public WorkOrder[] FindWorkOrders(
				WorkOrderSearchSpecification specification)
			{
				throw new NotImplementedException();
			}
		}

		private class TestStateCommandVisitor : StateCommandVisitor
		{
			public string ActualUrl;

			protected override void redirect(string url)
			{
				ActualUrl = url;
			}
		}

		public class StateCommandStub : IStateCommand
		{
			private readonly WorkOrderStatus _status;
			private readonly WorkOrder _workOrder;

			public StateCommandStub(WorkOrderStatus status, WorkOrder workOrder)
			{
				_status = status;
				_workOrder = workOrder;
			}

			public bool IsValid()
			{
				return true;
			}

			public void Execute(IStateCommandVisitor commandVisitor)
			{
			}

			public string TransitionVerbPresentTense
			{
				get { throw new NotImplementedException(); }
			}

			public bool Matches(string commandName)
			{
				throw new NotImplementedException();
			}

			public WorkOrderStatus GetBeginStatus()
			{
				return _status;
			}
		}

		[Test]
		public void EditWorkOrderShouldForwardToEditPageForCurrentWorkOrder()
		{
			var visitor = new TestStateCommandVisitor();
			var order = new WorkOrder {Number = "123"};
			visitor.EditWorkOrder(order);

			Assert.That(visitor.ActualUrl,
			            Is.EqualTo("~/workorder/edit?workordernumber=123"));
		}

		[Test]
		public void ShouldSaveWorkOrder()
		{
			var repository = new MockWorkOrderRepository();
			IStateCommandVisitor commandVisitor = new StateCommandVisitor(repository,
			                                                              null);
			var order = new WorkOrder();
			commandVisitor.SaveWorkOrder(order);

			Assert.That(repository.WorkOrderSaved, Is.EqualTo(order));
		}

		[Test]
		public void ShouldSendError()
		{
			var session = MockRepository.GenerateMock<IUserSession>();
			FlashMessage actualMessage = null;
			session.Expect(x => x.PushUserMessage(null))
				.IgnoreArguments().Do(new Action<FlashMessage>(
				                      	obj => actualMessage = obj));

			IStateCommandVisitor commandVisitor = new StateCommandVisitor(null, session);
			commandVisitor.SendError("whoa");

			session.VerifyAllExpectations();
			Assert.That(actualMessage.Type, Is.EqualTo(FlashMessage.MessageType.Error));
			Assert.That(actualMessage.Message, Is.EqualTo("whoa"));
		}

		[Test]
		public void ShouldSendMessage()
		{
			var session = MockRepository.GenerateMock<IUserSession>();
			FlashMessage actualMessage = null;
			session.Expect(x => x.PushUserMessage(null))
				.IgnoreArguments().Do(new Action<FlashMessage>(
				                      	obj => actualMessage = obj));

			IStateCommandVisitor commandVisitor = new StateCommandVisitor(null, session);
			commandVisitor.SendMessage("howdy pardner");

			session.VerifyAllExpectations();
			Assert.That(actualMessage.Type,
			            Is.EqualTo(FlashMessage.MessageType.Message));
			Assert.That(actualMessage.Message, Is.EqualTo("howdy pardner"));
		}
	}
}